﻿//    TestGenerator - experiment with piping data into ffmpeg in "pipefmt"
//    Copyright (C) 2012  Juergen Bohl

//    This program is free software: you can redistribute it and/or modify
//    it under the terms of the GNU General Public License as published by
//    the Free Software Foundation, either version 3 of the License, or
//    (at your option) any later version.

//    This program is distributed in the hope that it will be useful,
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//    GNU General Public License for more details.

//    You should have received a copy of the GNU General Public License
//    along with this program.  If not, see <http://www.gnu.org/licenses/>.

namespace TestGenerator
{
    #region using directives
    #endregion

    class Program
    {
        static void Main(string[] args)
        {
            Options opts = new Options();
            opts.Init(args);

            if (opts.OperationMode == OperationMode.OutputPipeFormatFile)
            {
                OutputPipeFormatFile(opts);
            }
            else if (opts.OperationMode == OperationMode.DriveFFMPEG)
            {
                OutputDriveFfmpeg(opts);
            }
        }

        private static void Output(Options opts, IAVSink sink)
        {
            BitmapGenerator bG = new BitmapGenerator();
            bG.Init(
                new BitmapGeneratorOptions()
                {
                    Width = opts.VideoFormat.Width,
                    Height = opts.VideoFormat.Height
                });

            AudioGenerator aG = null;
            if (opts.WithAudio)
            {
                aG = new AudioGenerator();
                if (opts.IntervalFramesCount > 0)
                {
                    // TODO: determine the number of audio samples per frame
                    const int samplesPerFrame = 1920;
                    aG.Init(opts.AudioFormat.SampleRate, 1000, sampleCountSine: opts.IntervalFramesCount * samplesPerFrame, sampleCountSilence: opts.IntervalFramesCount * samplesPerFrame);
                }
                else
                {
                    aG.Init(opts.AudioFormat.SampleRate, 1000);
                }
            }

            for (int n = 0; n < opts.NumberOfFrames; n++)
            {
                bG.GenerateNext();
                TestGenerator.LockInfo lockInfo = bG.Lock();
                sink.AddFrameRgb24(lockInfo.Ptr, lockInfo.Size, lockInfo.Stride);
                bG.Unlock(lockInfo);

                if (aG != null)
                {
                    short[] audio = aG.GetSamplesStereo(1920);
                    sink.AddAudioSamplesInterleaved(audio);
                }
            }
        }

        private static void OutputPipeFormatFile(Options options)
        {
            PipeFmtFileOutput pipeFmtFileOutput = new PipeFmtFileOutput();
            var pipeFmtInitOptions = new PipeFmtFileOutput.InitOptions(
                                                            options.OutputFileName,
                                                            options.VideoFormat,
                                                            options.AudioFormat);
            pipeFmtFileOutput.Initialize(pipeFmtInitOptions);
            Output(options, pipeFmtFileOutput);
            pipeFmtFileOutput.Dispose();
        }

        private static void OutputDriveFfmpeg(Options options)
        {
            FfmpegDriver ffmpegDriver = new FfmpegDriver();
            if (!string.IsNullOrEmpty(options.FfmpegExecutable))
            {
                ffmpegDriver.FileNameFfmpeg = options.FfmpegExecutable;
            }

            FfmpegDriverInitOptions initOptions = new FfmpegDriverInitOptions(
                                                           options.VideoFormat,
                                                           options.AudioFormat,
                                                           options.OutputFileName);
            ffmpegDriver.Initialize(initOptions);

            Output(options, ffmpegDriver);
            ffmpegDriver.Dispose();
        }
    }
}

//
// syntax:  -range 0-1000 -size 720x576 -audiogen sine,500,25 -output file=C:\test.pipefmt